package com.new4net.exe_stream.service.impl;

import com.new4net.exe_stream.instruction.BranchInstruction;
import com.new4net.exe_stream.instruction.impl.ExecutionInstruction;
import com.new4net.exe_stream.service.ExecutionInstructionService;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

public class SimpleExecutionInstructionService implements ExecutionInstructionService {
    List<ExecutionInstruction> executionInstructions = new ArrayList<>();
    @Override
    public synchronized void hosting(ExecutionInstruction instruction) {
        if(!executionInstructions.contains(instruction)){
            executionInstructions.add(instruction);

        }
    }

    @Override
    public synchronized List<ExecutionInstruction> listAll(int pageNum,int pageSize) {
        if(pageNum>0&&pageSize>0){
            List<ExecutionInstruction> result = new ArrayList<>();
            int size = executionInstructions.size();
            int start = (pageNum-1)*pageSize;
            int end = Math.min(pageNum*pageSize,size);
            if(start<size){
                int i=0;
                for(ExecutionInstruction executionInstruction:executionInstructions){
                    if(start<=i&&i<end){
                        result.add(executionInstruction);
                    }

                    i++;

                }
            }

            return result;

        }else if(pageSize<=0){
            return new ArrayList<>();
        }

        return executionInstructions;
    }

    @Override
    public synchronized int total() {
        return executionInstructions.size();
    }

    @Override
    public synchronized void retry(String id) {
        BranchInstruction branchInstruction =  getBranchInstruction(id);
        if(branchInstruction!=null){
            branchInstruction.retry();

        }
    }

    private BranchInstruction getBranchInstruction(String id) {

        return getBranchInstruction(executionInstructions,id);
    }
    private BranchInstruction getBranchInstruction(List<? extends BranchInstruction> executionInstructions, String id) {
        for(BranchInstruction instruction:executionInstructions){
            if(instruction.getInstructionId().equals(id)){
                return instruction;
            }else {
                List<BranchInstruction> branchInstructions =
                        (List<BranchInstruction>) instruction.getChildren()
                        .stream()
                        .filter(o -> o instanceof BranchInstruction)
                        .collect(Collectors.toList());
                if(branchInstructions.isEmpty()){
                    continue;
                }

                BranchInstruction branchInstruction =
                        getBranchInstruction(branchInstructions, id);
                if(branchInstruction!=null){
                    return branchInstruction;
                }

            }

        }

        return null;
    }

    @Override
    public synchronized void removeHosting(String id) {
        for(Iterator<ExecutionInstruction> iterator =
            executionInstructions.iterator();
                    iterator.hasNext();){
            ExecutionInstruction instruction =iterator.next();
            if(instruction.getInstructionId().equals(id)){
                iterator.remove();

            }
        }
    }
}
